package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/sirupsen/logrus"
	"net"
	"net/http"
	"os"
	"os/signal"
	"syscall"
)

type service struct {
	port     int
	listener net.Listener
	server   *http.Server
}

func NewService(port int) *service {
	return &service{
		port: port,
	}
}

func (s *service) Start() error {
	handler := http.NewServeMux()
	handler.HandleFunc("/", s.root)
	handler.HandleFunc("/healthz", s.healthz)

	s.server = new(http.Server)
	s.server.Addr = fmt.Sprintf(":%d", s.port)
	s.server.Handler = handler

	logrus.Infof("http server about to listen on port %d", s.port)
	err := s.server.ListenAndServe()
	if err == http.ErrServerClosed {
		logrus.Info("http server is closed")
		return nil
	}
	return err
}

func (s *service) Stop() error {
	logrus.Info("http server about to close")
	return s.server.Close()
}

func (s service) root(resp http.ResponseWriter, request *http.Request) {
	logrus.Infof("IP: %s, Status: %d", request.RemoteAddr, 200)
	version, ok := os.LookupEnv("VERSION")
	if !ok {
		version = "the env VERSION is not found"
	}

	headers := resp.Header()
	headers.Add("version", version)

	for key, values := range request.Header {
		for _, value := range values {
			headers.Add(key, value)
		}
	}

	_, err := resp.Write([]byte("OK"))
	if err != nil {
		logrus.Errorf("write body: %+v", err)
	}
}

func (s service) healthz(resp http.ResponseWriter, request *http.Request) {
	logrus.Infof("IP: %s, Status: %d", request.RemoteAddr, 200)
	body := map[string]string{
		"state": "UP",
	}

	data, _ := json.Marshal(body)
	_, err := resp.Write(data)
	if err != nil {
		logrus.Errorf("write body for healthz: %+v", err)
	}
}

func main() {
	port := 80
	flag.IntVar(&port, "port", 80, "The port for the http server to serve on")
	flag.Parse()

	service := NewService(port)

	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)

	go func() {
		<-ch
		if err := service.Stop(); err != nil {
			logrus.Fatalf("failure to close http server: %+v", err)
		}
	}()

	if err := service.Start(); err != nil {
		logrus.Errorf("failure to start the http server: %+v", err)
	}
}
